<?php

namespace app\admin\library;

use think\Db;
use think\Exception;
use app\admin\controller\course\Schedule;
use app\common\model\CommunityCodeConfig;
use app\common\model\CommunityCode;
use app\common\model\Community;
use app\admin\library\CommunityRedis;
use app\admin\model\Autoplan;
use think\Cache;
use think\Config;
use think\Request;
use app\common\model\CourseSchedule as ScheduleModel;

// 添加视图类的引用
use think\View;

class CommunityScheduler
{
    protected $timeSlotDetails = [];
    protected $redis;
    protected $request;
    protected $model;
    // 添加视图属性定义
    protected $view;

    public function __construct()
    {
        $redis = new CommunityRedis();
        $this->redis = $redis->getRedisInstance();
        $this->request = Request::instance();
        $this->model = new ScheduleModel();
        
        // 初始化视图对象，添加错误处理
        try {
            $this->view = new View();
            if ($this->view !== null) {
                // 设置默认模板路径
                $this->view->config('template.view_path', APP_PATH . 'admin/view/course/schedule/');
                
                // 获取公益项目列表
                $publicwelfareList = Db::name('fa_community_publicwelfare')
                    ->where('status', 1)
                    ->field('id, project_name')
                    ->select();
                $this->view->assign("publicwelfareList", $publicwelfareList);
            }
        } catch (\Exception $e) {
            // 如果View初始化失败，记录错误但不中断程序
            error_log('CommunityScheduler View initialization failed: ' . $e->getMessage());
            $this->view = null;
        }
    }

    /**
     * 对外公开的时间段详情获取方法（供控制器调用）
     */
    public function getDetailedTimeSlots($publicwelfare_id = 0)
    {
        return $this->getTimeSlotDetails($publicwelfare_id);
    }

    /**
     * 自动社区排课
     */
    public function generate($publicwelfare_id)
    {
        $autoplanModel = new Autoplan();
        // 获取该项目下的课程、社区、时区和时间段
        $courseData = $this->getCourseData($publicwelfare_id);
        $communityData = $this->getCommunityData($publicwelfare_id);
        $timeZoneData = $this->getTimeZoneData($publicwelfare_id);
        $timeSlotData = $this->getTimeSlotData($publicwelfare_id);
        $coursenameFromId = $this->model->getCourseCodeFromName($publicwelfare_id);
        $courses = array_keys($courseData);
        $communities = array_keys($communityData);
        $timeZones = array_keys($timeZoneData);

        // 检查数据库中已存在的社区，确保包含所有需要排课的社区
        $existingCommunities = Db::name('fa_course_schedule')
            ->where('publicwelfare_id', $publicwelfare_id)
            ->distinct(true)
            ->column('community_code');

        // 将数据库中存在但配置中没有的社区也加入排课列表
        foreach ($existingCommunities as $communityCode) {
            if (!isset($communityData[$communityCode])) {
                // 尝试从配置表获取社区名称
                $communityName = Db::name('fa_community_code_config')
                    ->where('code', $communityCode)
                    ->value('name');

                if (!$communityName) {
                    // 如果配置表中也没有，使用代码作为名称
                    $communityName = $communityCode;
                }

                $communityData[$communityCode] = $communityName;
                $communities[] = $communityCode;
                $debugInfo[] = "添加数据库中的社区到排课列表: {$communityCode} => {$communityName}";
            }
        }

        // 添加详细的调试信息
        $debugInfo[] = "=== 排课开始 ===";
        $debugInfo[] = "项目ID: {$publicwelfare_id}";
        $debugInfo[] = "课程总数: " . count($courses) . " (" . implode(', ', array_values($courseData)) . ")";
        $debugInfo[] = "社区总数: " . count($communities);

        // 检查现有的排课记录
        $debugInfo[] = "=== 检查现有排课记录 ===";
        $existingSchedules = Db::name('fa_course_schedule')
            ->where('publicwelfare_id', $publicwelfare_id)
            ->field('community_code, course_code, COUNT(*) as count')
            ->group('community_code')
            ->select();

        // 计算每个社区需要安排的课程数量
        $coursesPerCommunity = count($courses);
        $debugInfo[] = "每个社区需要安排课程数: {$coursesPerCommunity}";

        // 获取详细时间段数据
        $detailedTimeSlots = $this->getTimeSlotDetails($publicwelfare_id);

        // 按年、月、日、开始时间排序
        usort($detailedTimeSlots, function ($a, $b) {
            if ($a['year'] != $b['year']) {
                return $a['year'] - $b['year'];
            }
            if ($a['month'] != $b['month']) {
                return $a['month'] - $b['month'];
            }
            if ($a['day'] != $b['day']) {
                return $a['day'] - $b['day'];
            }
            return strcmp($a['startTime'], $b['startTime']);
        });

        // 1. 按月份分组日期
        $datesByMonth = [];
        foreach ($detailedTimeSlots as $timeSlot) {
            $monthKey = $timeSlot['year'] . '-' . $timeSlot['month'];
            $dateKey = $timeSlot['year'] . '-' . $timeSlot['month'] . '-' . $timeSlot['day'];

            if (!isset($datesByMonth[$monthKey])) {
                $datesByMonth[$monthKey] = [];
            }

            if (!isset($datesByMonth[$monthKey][$dateKey])) {
                $datesByMonth[$monthKey][$dateKey] = [];
            }

            $datesByMonth[$monthKey][$dateKey][] = $timeSlot;
        }

        // 4. 开始排课
        try {
            // 按月份排序
            uksort($datesByMonth, function ($a, $b) {
                return strtotime($a) - strtotime($b);
            });

            // 初始化变量
            $communityCoursesAssigned = [];
            $communityDateCoursesAssigned = [];
            foreach ($communities as $communityId) {
                $communityCoursesAssigned[$communityId] = 0;
                $communityDateCoursesAssigned[$communityId] = [];
            }

            $communityTimeSlotUsed = [];
            $courseTimeSlotUsed = [];
            $communityCoursesTaken = [];

            // 新增：全局课程时间冲突检查数组
            $globalCourseTimeSlotUsed = [];

            // 清空该项目的旧排课数据
            Db::name('fa_course_schedule')->where('publicwelfare_id', $publicwelfare_id)->delete();
            $debugInfo[] = "已清空项目 {$publicwelfare_id} 的旧排课数据";

            // 初始化每个社区的课程记录
            foreach ($communities as $communityId) {
                $communityCoursesTaken[$communityId] = [];
            }

            // 主排课循环
            $loopCount = 0;
            $insertCount = 0;
            $debugInfo[] = "=== 开始主排课循环 ===";
            $debugInfo[] = "月份数: " . count($datesByMonth);
            foreach ($datesByMonth as $monthKey => $datesInMonth) {
                //$debugInfo[] = "处理月份: {$monthKey}, 包含日期数: " . count($datesInMonth);
                foreach ($datesInMonth as $dateKey => $timeSlotsInDate) {
                    foreach ($timeSlotsInDate as $timeSlot) {
                        //$debugInfo[] = "处理时间段: {$timeSlot['start_time']} - {$timeSlot['end_time']}";
                        
                        // 构建全局时间标识符（不包含社区信息，用于检查课程时间冲突）
                        $globalTimeIdentifier = '';
                        if (is_array($timeSlot)) {
                            $globalTimeIdentifier = $timeSlot['year'] . '_' .
                                $timeSlot['month'] . '_' .
                                $timeSlot['day'] . '_' .
                                $timeSlot['startTime'] . '-' .
                                $timeSlot['endTime'];
                        } else {
                            $parts = explode(' ', $timeSlot);
                            if (count($parts) >= 2) {
                                $globalTimeIdentifier = $parts[0] . '_' . $parts[1]; // 日期_时间段
                            }
                        }

                        foreach ($communities as $communityId) {

                            foreach ($courses as $courseId) {
                                // 检查这个社区是否已安排过这个课程
                                if (
                                    isset($communityCoursesTaken[$communityId]) &&
                                    is_array($communityCoursesTaken[$communityId]) &&
                                    in_array($courseId, $communityCoursesTaken[$communityId])
                                ) {
                                    continue;
                                }

                                // 新增：检查同一时间段是否已经有其他社区在上同一门课程
                                $globalCourseTimeKey = $courseId . '_' . $globalTimeIdentifier;
                                if (isset($globalCourseTimeSlotUsed[$globalCourseTimeKey])) {
                                    // 该课程在此时间段已被其他社区占用，跳过
                                    continue;
                                }

                                // 检查社区是否已安排完所有课程
                                if ($communityCoursesAssigned[$communityId] >= $coursesPerCommunity) {
                                    continue;
                                }

                                // 检查社区是否已在当天安排过课程
                                if (
                                    isset($communityDateCoursesAssigned[$communityId]) &&
                                    is_array($communityDateCoursesAssigned[$communityId]) &&
                                    isset($communityDateCoursesAssigned[$communityId][$dateKey]) &&
                                    $communityDateCoursesAssigned[$communityId][$dateKey] > 0
                                ) {
                                    // 如果社区当天已排课，则跳过
                                    continue;
                                }

                                // 生成唯一键检查时间段是否已使用
                                $timeSlotKey = $communityId . '_';
                                if (is_array($timeSlot)) {
                                    $timeSlotKey .= $timeSlot['year'] . '_' .
                                        $timeSlot['month'] . '_' .
                                        $timeSlot['day'] . '_' .
                                        $timeSlot['startTime'] . '-' .
                                        $timeSlot['endTime'];
                                } else {
                                    $timeSlotKey .= $timeSlot;
                                }

                                // 检查时间段是否已使用
                                if (isset($communityTimeSlotUsed[$timeSlotKey])) {
                                    continue;
                                }

                                // 获取ocation信息
                                $ocationInfo = Db::name('fa_community_code_config')
                                    ->alias("cc")
                                    ->join("fa_ocation o", "o.name=cc.name and rel_type=2")
                                    ->where('code', $communityId)
                                    ->where('publicwelfare_id', $publicwelfare_id)
                                    ->field("o.*")
                                    ->find();
                                $ocation_id = $ocationInfo['id'];
//

                                //检查时间段在正式排课表内是否已使用 ===yzs1013
                                $autoplan = $autoplanModel->checkTimeslotOcationFormAutoplan($timeSlot, $ocation_id);
                                if ($autoplan) {
                                    $debugInfo[] = "跳过已存在的时间段: {$timeSlot['year']}-{$timeSlot['month']}-{$timeSlot['day']} {$timeSlot['startTime']}-{$timeSlot['endTime']}";
                                    continue;
                                }

                                // 构建时间标识符（不包含社区信息）
                                $timeIdentifier = '';
                                if (is_array($timeSlot)) {
                                    $timeIdentifier = $timeSlot['year'] . '_' .
                                        $timeSlot['month'] . '_' .
                                        $timeSlot['day'] . '_' .
                                        $timeSlot['startTime'] . '-' .
                                        $timeSlot['endTime'];
                                } else {
                                    $parts = explode(' ', $timeSlot);
                                    if (count($parts) >= 2) {
                                        $timeIdentifier = $parts[0] . '_' . $parts[1]; // 日期_时间段
                                    }
                                }

                                try {
                                    // 创建排课记录
                                    $dateParts = is_array($timeSlot) ? null : explode('-', explode(' ', $timeSlot)[0]);
                                    $timeSlotCode = $timeSlot['id']; //is_array($timeSlot) ? $timeSlot['startTime'] . "-" . $timeSlot['endTime'] : ($timeSlot['code'] ?? 0);
                                    $timeZoneCode = is_array($timeSlot) ? ($timeSlot['time_zone_code'] ?? '') : '';

                                    // 请在这里组织数据，插入到 Autoplantemp 表,参考autoplan.php的排课数据用insertUpdate方法
                                    // 获取课程信息
                                    $courseInfo = Db::name('community_course_config')
                                        ->where('code',$courseId)
                                        ->where('publicwelfare_id', $publicwelfare_id)
                                        ->find();

                                    if ($ocationInfo) {
                                        $community_id = $this->findCommunityIdRecursive($ocationInfo['id']);
                                        if (!$community_id) {
                                            $community_id = $ocationInfo['id'];
                                        }
                                    } else {
                                        $community_id = 0;
                                    }
//city,school_id,classes_id,ocation_id,community_id
                                    // 获取公益项目信息
                                    $publicwelfareInfo = Db::name('fa_community_publicwelfare')
                                        ->where('id', $publicwelfare_id)
                                        ->find();

                                    // 获取社区名称
                                    $communityName = $communityData[$communityId] ?? $communityId;

                                    // 获取课程名称
                                    $courseName = $courseData[$courseId] ?? $courseId;

                                    // 构造班级名称：社区名+课程名+公益项目名
                                    $className = "【" . $communityName . "】" . $courseName . ($publicwelfareInfo['project_name'] ?? '');

                                    $parentOcations = model("\app\admin\model\Ocation")->getParentOcations($ocation_id);
                                    $parentTeachingOcationId = $parentOcations["parentTeachingOcationId"];
                                    $topTeachingOcationId = $parentOcations["topTeachingOcationId"];
                                    $areaTeachingOcationId = $parentOcations["areaTeachingOcationId"];

                                    $courseTimeKey = $courseId . '_' . $timeIdentifier;

                                    // 构造班级数据
                                    $classData = [
                                        'school_id' => session('admin.school_id'), // 使用session函数安全获取学校ID
                                        'name' => $communityName . "班级",
                                        'classes_type' => 2, // 默认班级类型
                                        'nianji' => '', // 年级（社区排课可为空）
                                        'xueqi' => '', // 学期（社区排课可为空）
                                        'ocation_id' => $ocation_id,
                                        'qishu' => 0, // 使用当前选中的课程ID
                                        'class_type' => 1, // 班级类型
                                        'subject_lv' => $courseInfo['id'], // 使用当前选中的课程ID
                                        'status' => 1,
                                        'weigh' => 0, // 权重
                                        'class_index' => 1, // 默认第1节课
                                        'oindex' => 1, // 默认第1节
                                        'oindex_count' => 1, // 默认1节课
                                        'count_total' => 1, // 默认总共1节课
                                        'bz' => '自动排课生成',
                                        'parent_teaching_ocation_id' => $parentTeachingOcationId, // 上级教学点ID
                                        'top_teaching_ocation_id' => $topTeachingOcationId, // 一级教学点ID
                                        'area_teaching_ocation_id' => $areaTeachingOcationId, // 一级教学点ID
                                        'publicwelfare_id' => $publicwelfare_id, // 项目ID
                                        'community_id' => $community_id, // 社区ID
                                        'is_free' => 1, // 是否免费
                                    ];
                                    // 检查是否已存在相同的学校和班级名记录
                                    $existingClass = Db::name('fa_ocation_class')
                                        ->where('school_id', session('admin.school_id'))
                                        ->where('classes_type', 2)
                                        ->where('ocation_id', $ocation_id)
                                        ->find();

                                    // 如果不存在相同记录则插入，否则使用已存在的记录ID
                                    if (!$existingClass) {
                                        // 构建INSERT语句
                                        $fields = array_keys($classData);
                                        $values = array_values($classData);
                                        $fieldStr = '`' . implode('`, `', $fields) . '`';
                                        $valueStr = "'" . implode("', '", $values) . "'";
                                        
                                        $sql = "INSERT INTO `fa_ocation_class` ($fieldStr) VALUES ($valueStr)";
                                        
                                        // 执行INSERT语句
                                        $ocation_class_id = Db::execute($sql);
                                    } else {
                                        $ocation_class_id = $existingClass['id'];
                                    }


                                    $scheduleData = [
                                        'publicwelfare_id' => $publicwelfare_id,
                                        'school_id' => session('admin.school_id') ? session('admin.school_id') : 0, // 使用session函数安全获取学校ID
                                        'community_code' => $communityId,
                                        'course_code' => $courseId,
                                        'year' => is_array($timeSlot) ? $timeSlot['year'] : $dateParts[0],
                                        'month' => is_array($timeSlot) ? $timeSlot['month'] : $dateParts[1],
                                        'day' => is_array($timeSlot) ? $timeSlot['day'] : $dateParts[2],
                                        'time_slot_code' => $timeSlotCode,
                                        'time_zone_code' => $timeZoneCode,
                                        'timeslot' => is_array($timeSlot) ? ($timeSlot['startTime'] . '-' . $timeSlot['endTime']) : $timeSlot,
                                        'status' => 1,
                                        'create_time' => time(),
                                        'update_time' => time(),
                                        'ocation_id' => $ocation_id,
                                        'classes_id' => $ocation_class_id,
                                        'city_id' => session('admin.city_id'),
                                    ];
                                    $courseInfo['teacher_id'] = 0;
                                    $courseInfo['manager_id'] = 0;
                                    $courseInfo['id'] = 0;
                                    $courseInfo['city_id'] = session('admin.city_id');
                                    // 插入排课记录
                                    $schedule_id = model('CourseSchedule')->insertUpdate($scheduleData, ["year", "month", "day", "time_slot_code", "community_code", "course_code"]);
                                    $insertCount++;
                                    $loopCount++;
                                    // 准备调用insertAutoplantemp所需的参数
                                    $timeSlotInfo = [
                                        'start_time' => is_array($timeSlot) ? $timeSlot['startTime'] : '',
                                        'end_time' => is_array($timeSlot) ? $timeSlot['endTime'] : ''
                                    ];

                                    $ocationId = $ocationInfo['id'] ?? 0;

                                    // 调用insertAutoplantemp方法，传入所有必需参数
                                    $this->insertAutoplantemp($publicwelfare_id, $scheduleData, $timeSlotInfo, $ocationId, $ocation_class_id, $courseInfo, $timeZoneCode, $parentTeachingOcationId, $topTeachingOcationId, $areaTeachingOcationId, $community_id, $courseId);

                                    // 更新记录状态
                                    $communityTimeSlotUsed[$timeSlotKey] = true;
                                    $courseTimeSlotUsed[$courseTimeKey] = true;

                                    // 新增：标记该课程在此时间段已被全局占用
                                    $globalCourseTimeSlotUsed[$globalCourseTimeKey] = $communityId;

                                    // 记录该社区已经上过的课程
                                    $communityCoursesTaken[$communityId][] = $courseId;

                                    // 更新社区课程计数
                                    $communityCoursesAssigned[$communityId]++;

                                    // 更新社区当天课程计数
                                    if (!isset($communityDateCoursesAssigned[$communityId][$dateKey])) {
                                        $communityDateCoursesAssigned[$communityId][$dateKey] = 0;
                                    }
                                    $communityDateCoursesAssigned[$communityId][$dateKey]++;

                                    $courseName = $courseData[$courseId] ?? $courseId;
                                    $communityName = $communityData[$communityId] ?? $communityId;


                                    //$debugInfo[] = "排课成功: {$communityName}({$communityId}) - {$courseName}({$courseId}) - {$scheduleData['year']}-{$scheduleData['month']}-{$scheduleData['day']} {$scheduleData['timeslot']}";
                                } catch (\Exception $e) {
                                    $debugInfo[] = "排课失败: " . $e->getMessage();
                                    continue;
                                }
                            }
                        }
                    }
                }
            }
            $debugInfo[] = "主排课循环总执行次数: {$loopCount}";
            $debugInfo[] = "实际插入记录数: {$insertCount}";

            // 主排课循环结束后，添加详细的统计信息
            $debugInfo[] = "=== 主排课结束，统计结果 ===";
            foreach ($communities as $communityId) {
                $assigned = $communityCoursesAssigned[$communityId] ?? 0;
                $communityName = $communityData[$communityId] ?? $communityId;
                //$debugInfo[] = "社区 {$communityId}({$communityName}) 实际安排课程数: {$assigned}/{$coursesPerCommunity}";
            }

            // 在补课检查前，重新统计每个社区的实际课程数
            $debugInfo[] = "=== 重新统计每个社区的实际课程数 ===";
            $actualCommunityCourseCounts = [];

            foreach ($communityData as $communityCode => $communityName) {
                $actualCount = Db::name('fa_course_schedule')
                    ->where('publicwelfare_id', $publicwelfare_id)
                    ->where('community_code', $communityCode)
                    ->count();
                $actualCommunityCourseCounts[$communityCode] = $actualCount;
            }

            // 改进的补充排课机制
            $debugInfo[] = "=== 开始补充排课检查 ===";

            // 获取所有需要排课的社区（包括数据库中存在的）
            $allCommunitiesNeedingSchedule = array_unique(array_merge(
                array_keys($communityData),
                $existingCommunities
            ));

            $incompleteCommunities = [];

            foreach ($allCommunitiesNeedingSchedule as $communityCode) {
                $actualCount = Db::name('fa_course_schedule')
                    ->where('publicwelfare_id', $publicwelfare_id)
                    ->where('community_code', $communityCode)
                    ->count();

                if ($actualCount < $coursesPerCommunity) {
                    $needed = $coursesPerCommunity - $actualCount;
                    $incompleteCommunities[$communityCode] = $needed;

                    $communityName = $communityData[$communityCode] ?? $communityCode;
                    $debugInfo[] = "社区未完成: {$communityCode}({$communityName}) 现有 {$actualCount} 门，还需要 {$needed} 门课程";

                    //                    // 特别标记凤翔社区
                    //                    if (strpos($communityCode, '凤翔') !== false || $communityCode === '社区64') {
                    //                        $debugInfo[] = "*** 凤翔社区需要补充排课: {$communityCode} 还需要 {$needed} 门课程 ***";
                    //                    }
                }
            }

            // 补充排课逻辑
            if (!empty($incompleteCommunities)) {
                $debugInfo[] = "开始为 " . count($incompleteCommunities) . " 个社区补充排课";

                foreach ($incompleteCommunities as $communityCode => $needed) {
                    $debugInfo[] = "正在为社区 {$communityCode} 补充 {$needed} 门课程";

                    for ($i = 0; $i < $needed; $i++) {
                        // 查找可用的时间段和课程
                        $availableSlot = null;
                        $availableCourse = null;

                        foreach ($detailedTimeSlots as $timeSlot) {
                            $timeSlotKey = $this->generateTimeSlotKey(
                                $timeSlot,
                                $communityCode
                            );

                            // 检查这个时间段是否已被该社区使用
                            if (isset($communityTimeSlotUsed[$timeSlotKey])) {
                                continue;
                            }

                            // 查找可用课程
                            foreach ($courses as $courseCode) {
                                $timeIdentifier = $timeSlot['year'] . '_' .
                                    $timeSlot['month'] . '_' .
                                    $timeSlot['day'] . '_' .
                                    $timeSlot['startTime'] . '-' .
                                    $timeSlot['endTime'];
                                $courseTimeSlotKey = $courseCode . '_' . $timeIdentifier;

                                // 检查课程在该时间段是否已被使用
                                if (isset($courseTimeSlotUsed[$courseTimeSlotKey])) {
                                    continue;
                                }

                                $availableSlot = $timeSlot;
                                $availableCourse = $courseCode;
                                break 2;
                            }
                        }

                        if ($availableSlot && $availableCourse) {
                            // 创建排课记录
                            $scheduleData = [
                                'publicwelfare_id' => $publicwelfare_id,
                                'community_code' => $communityCode,
                                'course_code' => $availableCourse,
                                'year' => $availableSlot['year'],
                                'month' => $availableSlot['month'],
                                'day' => $availableSlot['day'],
                                'time_slot_code' => $availableSlot['id'],
                                'time_zone_code' => $availableSlot['time_zone_code'] ?? '',
                                'timeslot' => $availableSlot['startTime'] . '-' . $availableSlot['endTime'],
                                'status' => 1,
                                'create_time' => time(),
                                'update_time' => time(),
                                'remark' => '补充排课'
                            ];

                            Db::name('fa_course_schedule')->insert($scheduleData);

                            // 更新使用记录
                            $timeSlotKey = $this->generateTimeSlotKey(
                                $availableSlot,
                                $communityCode
                            );

                            $communityTimeSlotUsed[$timeSlotKey] = true;
                            $timeIdentifier = $availableSlot['year'] . '_' .
                                $availableSlot['month'] . '_' .
                                $availableSlot['day'] . '_' .
                                $availableSlot['startTime'] . '-' .
                                $availableSlot['endTime'];
                            $courseTimeSlotUsed[$availableCourse . '_' . $timeIdentifier] = true;

                            $courseName = $courseData[$availableCourse] ?? $availableCourse;
                            $communityName = $communityData[$communityCode] ?? $communityCode;

                            $debugInfo[] = "补充排课成功: {$communityName}({$communityCode}) - {$courseName}({$availableCourse}) - {$availableSlot['year']}-{$availableSlot['month']}-{$availableSlot['day']} {$availableSlot['startTime']}-{$availableSlot['endTime']}";

                            // 特别标记凤翔社区的补充排课
                            if (strpos($communityCode, '凤翔') !== false || $communityCode === '社区64') {
                                $debugInfo[] = "*** 凤翔社区补充排课: {$courseName} ***";
                            }
                        } else {
                            $debugInfo[] = "警告: 无法为社区 {$communityCode} 找到可用的时间段和课程";
                        }
                    }
                }
            } else {
                $debugInfo[] = "所有社区课程安排完整，无需补课";
            }

            // 新增：调用教学点课程表更新方法
            $updateResult = $this->updateOcationClasses($publicwelfare_id, $debugInfo);
            if ($updateResult['code'] == 0) {
                return ['code' => 0, 'msg' => '排课完成但更新教学点课程表失败: ' . $updateResult['msg'], 'debug' => $debugInfo];
            }

            // 合并调试信息
            $debugInfo = array_merge($debugInfo, $updateResult['debug'] ?? []);

            return ['code' => 1, 'msg' => '排课完成', 'debug' => $debugInfo];
        } catch (Exception $e) {
            return ['code' => 0, 'msg' => '排课失败: ' . $e->getMessage(), 'data' => [], 'debug' => $debugInfo];
        }
    }

    /**
     * 更新教学点课程表
     * @param int $publicwelfare_id 公益项目ID
     * @param array $debugInfo 调试信息数组
     * @return array 返回结果fv
     */
    protected function updateOcationClasses($publicwelfare_id, &$debugInfo = [])
    {
        try {
            $debugInfo[] = "=== 开始更新教学点课程表 ===";

            // 1. 获取自动排课生成的数据
            $scheduleData = Db::name('fa_course_schedule')
                ->where('publicwelfare_id', $publicwelfare_id)
                ->where('status', 1)
                ->select();

            if (empty($scheduleData)) {
                $debugInfo[] = "未找到排课数据，跳过教学点课程表更新";
                return ['code' => 1, 'msg' => '成功', 'debug' => $debugInfo];
            }

            $debugInfo[] = "找到 " . count($scheduleData) . " 条排课记录";

            // 2. 按教学点分组排课数据
            $ocationScheduleData = [];
            foreach ($scheduleData as $schedule) {
                $ocationId = $schedule['ocation_id'] ?? 0;
                if ($ocationId > 0) {
                    if (!isset($ocationScheduleData[$ocationId])) {
                        $ocationScheduleData[$ocationId] = [];
                    }
                    $ocationScheduleData[$ocationId][] = $schedule;
                }
            }

            $debugInfo[] = "涉及 " . count($ocationScheduleData) . " 个教学点";

            // 3. 更新每个教学点的课程表
            foreach ($ocationScheduleData as $ocationId => $schedules) {
                $result = $this->updateSingleOcationClass($ocationId, $schedules, $debugInfo);
                if ($result['code'] == 0) {
                    return $result;
                }
            }

            $debugInfo[] = "=== 教学点课程表更新完成 ===";
            return ['code' => 1, 'msg' => '更新成功', 'debug' => $debugInfo];
        } catch (\Exception $e) {
            $debugInfo[] = "更新教学点课程表失败: " . $e->getMessage();
            file_put_contents(
                $_SERVER["DOCUMENT_ROOT"] . "/../runtime/log/ocation_class_update_error.log",
                date('Y-m-d H:i:s') . " - " . $e->getMessage() . "\n",
                FILE_APPEND
            );
            return ['code' => 0, 'msg' => $e->getMessage(), 'debug' => $debugInfo];
        }
    }

    /**
     * 更新单个教学点的课程表
     * @param int $ocationId 教学点ID
     * @param array $schedules 排课数据
     * @param array $debugInfo 调试信息数组
     * @return array 返回结果
     */
    protected function updateSingleOcationClass($ocationId, $schedules, &$debugInfo = [])
    {
        try {
            // 1. 获取教学点信息
            $ocation = Db::name('fa_ocation')->where('id', $ocationId)->find();
            if (!$ocation) {
                $debugInfo[] = "教学点ID {$ocationId} 不存在，跳过";
                return ['code' => 1, 'msg' => '成功'];
            }

            $debugInfo[] = "处理教学点: {$ocation['name']} (ID: {$ocationId})";

            // 2. 查询现有的教学点课程记录
            $existingOcationClass = Db::name('fa_ocation_class')
                ->where('ocation_id', $ocationId)
                ->find();

            // 3. 准备教学点课程数据
            $ocationClassData = [
                'ocation_id' => $ocationId,
                'name' => $ocation['name'] . '班',
                'original_name' => $ocation['name'],
                'status' => 1,
                'weigh' => 0,
                'update_time' => date('Y-m-d H:i:s'),
                'community_id' => $schedules[0]['community_id'] ?? null,
                'description' => '自动排课生成，包含' . count($schedules) . '个课程'
            ];

            $ocationClassId = null;

            if ($existingOcationClass) {
                // 更新现有记录
                Db::name('fa_ocation_class')
                    ->where('id', $existingOcationClass['id'])
                    ->update($ocationClassData);
                $ocationClassId = $existingOcationClass['id'];
                $debugInfo[] = "更新现有教学点课程记录: {$ocation['name']}班";
            } else {
                // 创建新记录
                $ocationClassData['sequence_number'] = \app\admin\model\OcationClass::getNextSequence();
                $ocationClassData['create_time'] = date('Y-m-d H:i:s');
                $ocationClassId = Db::name('fa_ocation_class')->insertGetId($ocationClassData);
                $debugInfo[] = "创建新教学点课程记录: {$ocation['name']}班";
            }

            // 4. 更新课程关联关系
            $result = $this->updateOcationClassCourses($ocationClassId, $schedules, $debugInfo);
            if ($result['code'] == 0) {
                return $result;
            }

            return ['code' => 1, 'msg' => '成功'];
        } catch (\Exception $e) {
            $debugInfo[] = "更新教学点 {$ocationId} 课程表失败: " . $e->getMessage();
            return ['code' => 0, 'msg' => $e->getMessage()];
        }
    }

    /**
     * 更新教学点课程关联关系
     * @param int $ocationClassId 教学点课程ID
     * @param array $schedules 排课数据
     * @param array $debugInfo 调试信息数组
     * @return array 返回结果
     */
    protected function updateOcationClassCourses($ocationClassId, $schedules, &$debugInfo = [])
    {
        try {
            // 2. 从排课数据中提取班级ID
            $scheduleClassIds = [];
            foreach ($schedules as $schedule) {
                if (!empty($schedule['classes_id'])) {
                    $scheduleClassIds[] = $schedule['classes_id'];
                }
            }

            $scheduleClassIds = array_unique($scheduleClassIds);
            $debugInfo[] = "需要关联的班级数量: " . count($scheduleClassIds);

            // 3. 由于class_id有唯一约束，需要特殊处理
            $successCount = 0;
            $conflictCount = 0;
            $updateCount = 0;

            foreach ($scheduleClassIds as $classId) {
                // 检查该class_id是否已经存在于任何教学点班级中
                $existingRecord = Db::name('fa_ocation_class_course')
                    ->where('class_id', $classId)
                    ->find();

                if ($existingRecord) {
                    if ($existingRecord['ocation_class_id'] == $ocationClassId) {
                        // 如果已经关联到当前教学点班级，只需要确保状态为1
                        if ($existingRecord['status'] != 1) {
                            Db::name('fa_ocation_class_course')
                                ->where('id', $existingRecord['id'])
                                ->update([
                                    'status' => 1,
                                    'update_time' => date('Y-m-d H:i:s')
                                ]);
                            $updateCount++;
                        }
                    } else {
                        // 如果已经关联到其他教学点班级，需要转移关联
                        Db::name('fa_ocation_class_course')
                            ->where('id', $existingRecord['id'])
                            ->update([
                                'ocation_class_id' => $ocationClassId,
                                'status' => 1,
                                'update_time' => date('Y-m-d H:i:s')
                            ]);
                        $updateCount++;
                        $debugInfo[] = "转移班级 {$classId} 的关联到当前教学点班级";
                    }
                } else {
                    // 如果不存在，则新增记录
                    try {
                        Db::name('fa_ocation_class_course')->insert([
                            'ocation_class_id' => $ocationClassId,
                            'class_id' => $classId,
                            'status' => 1,
                            'create_time' => date('Y-m-d H:i:s'),
                            'update_time' => date('Y-m-d H:i:s')
                        ]);
                        $successCount++;
                    } catch (\Exception $e) {
                        $conflictCount++;
                        $debugInfo[] = "班级 {$classId} 插入失败，可能存在并发冲突: " . $e->getMessage();
                    }
                }
            }

            if ($successCount > 0) {
                $debugInfo[] = "新增课程关联记录: {$successCount} 条";
            }
            if ($updateCount > 0) {
                $debugInfo[] = "更新课程关联记录: {$updateCount} 条";
            }
            if ($conflictCount > 0) {
                $debugInfo[] = "冲突的课程关联记录: {$conflictCount} 条";
            }

            return ['code' => 1, 'msg' => '成功'];
        } catch (\Exception $e) {
            $debugInfo[] = "更新课程关联关系失败: " . $e->getMessage();
            return ['code' => 0, 'msg' => $e->getMessage()];
        }
    }

    /**
     * 获取课程数据，使用整数ID作为键值
     */
    protected function getCourseData($publicwelfare_id = 0)
    {
        // 从数据库直接获取课程数据，确保使用整数ID
        $courses = Db::name('fa_community_course_config')
            ->where('status', 1)
            ->where('delete_time', null)
            ->field('code, name')
            ->select();

        $list = [];
        foreach ($courses as $course) {
            $list[$course['code']] = $course['name'];
        }

        // 如果没有数据，返回默认列表
        if (empty($list)) {
            return [
                1 => '音乐',
                2 => '舞蹈',
                3 => '书法',
                4 => '绘画',
                5 => '钢琴',
                6 => '太极',
                7 => '剪纸',
                8 => '中医',
                9 => '国画',
                10 => '生活',
                11 => '运动',
                12 => '主持'
            ];
        }

        return $list;
    }

    /**
     * 获取社区数据，使用整数ID作为键值
     */
    protected function getCommunityData($publicwelfare_id = 0)
    {
        // 从数据库直接获取社区数据，确保使用整数ID
        $communities = Db::name('fa_community_code_config')
            ->where('status', 1)
            ->field('code, name')
            ->select();

        $list = [];
        foreach ($communities as $community) {
            $list[$community['code']] = $community['name'];
        }

        // 如果没有数据，返回默认列表
        if (empty($list)) {
            $list = [];
            for ($i = 1; $i <= 5; $i++) {
                $list[$i] = chr(64 + $i) . '社区'; // A-E社区
            }
        }

        return $list;
    }

    /**
     * 获取时区数据，使用整数ID作为键值
     */
    protected function getTimeZoneData($publicwelfare_id = 0)
    {
        // 从数据库直接获取时区数据，确保使用整数ID
        $timezones = Db::name('community_timezone_config')
            ->where('status', 1)
            ->where('delete_time', null)
            ->field('code, name')
            ->select();

        $list = [];
        foreach ($timezones as $timezone) {
            $list[$timezone['code']] = $timezone['name'];
        }

        // 如果没有数据，返回默认列表
        if (empty($list)) {
            return [
                1 => '上午',
                2 => '下午',
                3 => '晚上'
            ];
        }

        return $list;
    }

    /**
     * 获取时间段的详细信息，包括天数
     */
    protected function getTimeSlotDetails($publicwelfare_id = 0)
    {
        // 从数据库直接获取时间段数据
        $result = Db::name('fa_community_timeslot_config')
            ->where('status', 1)
            ->where('delete_time', null)
            ->field('id, code, name, day, start_time, end_time')
            ->select();
        $this->timeSlotDetails = $result;

        // 获取时区数据，用于获取年份和月份
        // 修改开始：根据项目开始日期动态生成时区数据
        $projectInfo = Db::name('fa_community_publicwelfare')
            ->where('id', $publicwelfare_id)
            ->field('start_time,community_id')
            ->find();

        if ($projectInfo && !empty($projectInfo['start_time'])) {
            $startDate = $projectInfo['start_time'];
            $startYear = date('Y', $startDate);
            $startMonth = date('n', $startDate);
            $community_id = $projectInfo['community_id'];
            // 检查现有数据是否从正确的月份开始
            $firstTimeZone = Db::name('fa_community_timezone_config')
                ->order('id', 'asc')
                ->find();

            $needRegenerate = true;
            if ($firstTimeZone) {
                // 检查第一条记录是否匹配开始日期
                if (preg_match('/(\d+)年(\d+)月/', $firstTimeZone['name'], $matches)) {
                    $firstYear = (int)$matches[1];
                    $firstMonth = (int)$matches[2];
                    if ($firstYear == $startYear && $firstMonth == $startMonth) {
                        $needRegenerate = false;
                    }
                }
            }

            if ($needRegenerate) {
                // 清空现有数据并重新生成6个月的记录
                Db::name('fa_community_timezone_config')->where('1=1')->delete();

                for ($i = 0; $i < 6; $i++) {
                    $currentMonth = $startMonth + $i;
                    $currentYear = $startYear;

                    // 处理跨年情况
                    if ($currentMonth > 12) {
                        $currentYear += floor(($currentMonth - 1) / 12);
                        $currentMonth = (($currentMonth - 1) % 12) + 1;
                    }

                    $data = [
                        'code' => '时期' . ($i + 1),
                        'name' => $currentYear . '年' . sprintf('%02d', $currentMonth) . '月', // 修改：月份补零
                        'publicwelfare_id' => $publicwelfare_id,
                        'community_id' => $community_id,
                        'status' => 1,
                        'create_time' => time()
                    ];

                    Db::name('fa_community_timezone_config')->insert($data);
                }
            }
        }

        $timeZoneData = Db::name('fa_community_timezone_config')
            ->field('id, code, name')
            ->select();
        // 修改结束

        $timeZones = [];
        foreach ($timeZoneData as $zone) {
            preg_match('/(\d+)年(\d+)月/', $zone['name'], $matches);
            $timeZones[$zone['code']] = [
                'year' => $matches[1] ?? date('Y'), // 如果没有年份，使用当前年份
                'month' => $matches[2] // 如果没有month，使用code作为月份
            ];
        }

        $list = [];
        $currentMonth = date('n');
        $currentYear = date('Y');

        // 生成时间段列表，并为每个时间段生成对应的时区数据
        foreach ($result as $key => $value) {
            $days = explode(',', $value['day']);
            foreach ($days as $k => $day) {
                // 为每个时区生成一个时间段条目
                foreach ($timeZones as $timeZoneCode => $timeZoneInfo) {
                    $list[] = array(
                        'id' => $value['code'],
                        'day' => intval($day),
                        'month' => $timeZoneInfo['month'],
                        'year' => $timeZoneInfo['year'],
                        'time_zone_code' => $timeZoneCode,
                        'startTime' => $value['start_time'],
                        'endTime' => $value['end_time'],
                        'text' => $day . "号 " . $value['start_time'] . "-" . $value['end_time'],
                        'originalText' => $value['start_time'] . "-" . $value['end_time'],
                    );
                }
            }
        }
        return $list;
    }

    /**
     * 获取时间段数据，使用整数ID作为键值
     */
    protected function getTimeSlotData($publicwelfare_id = 0)
    {
        // 从数据库直接获取时间段数据，确保使用整数ID
        $timeslots = Db::name('community_timeslot_config')
            ->where('status', 1)
            ->where('delete_time', null)
            ->field('id, code,name, day, start_time, end_time')
            ->select();

        $list = [];
        foreach ($timeslots as $timeslot) {
            // 如果 name 字段已经包含完整的显示名称，直接使用
            if (!empty($timeslot['name'])) {
                $list[$timeslot['code']] = $timeslot['name'];
            } else {
                // 否则组合日期和时间
                $startTime = date('H:i', strtotime($timeslot['start_time']));
                $endTime = date('H:i', strtotime($timeslot['end_time']));
                $list[$timeslot['code']] = $timeslot['day'] . '号 ' . $startTime . '-' . $endTime;
            }
        }

        // 如果没有数据，返回默认列表
        if (empty($list)) {
            $days = [20, 25, 30];
            $times = [
                '上午8:30-9:10',
                '上午9:20-10:10',
                '下午15:00-15:50'
            ];

            $list = [];
            $index = 1;
            foreach ($days as $day) {
                foreach ($times as $time) {
                    $list[$index] = $day . '号' . $time;
                    $index++;
                }
            }
        }

        return $list;
    }

    /**
     * 生成时间段键值
     */
    protected function generateTimeSlotKey($timeSlot, $communityId)
    {
        $timeSlotKey = $communityId . '_';
        if (is_array($timeSlot)) {
            $timeSlotKey .= $timeSlot['year'] . '_' .
                $timeSlot['month'] . '_' .
                $timeSlot['day'] . '_' .
                $timeSlot['startTime'] . '-' .
                $timeSlot['endTime'];
        } else {
            // 如果是字符串，假设格式为"Y-m-d H:i-H:i"
            $parts = explode(' ', $timeSlot);
            if (count($parts) >= 2) {
                $dateParts = explode('-', $parts[0]);
                $timeParts = explode('-', $parts[1]);

                if (count($dateParts) >= 3 && count($timeParts) >= 2) {
                    $timeSlotKey .= $dateParts[0] . '_' .  // year
                        $dateParts[1] . '_' .  // month
                        $dateParts[2] . '_' .  // day
                        $timeParts[0] . '-' .  // startTime
                        $timeParts[1];         // endTime
                }
            }
        }

        return $timeSlotKey;
    }

    /**
     * 获取指定时间段的可用课程
     */
    protected function getAvailableCoursesForTimeSlot($timeSlot, $communityId, $courseData, $courseTimeSlotUsed, $communityCoursesTaken)
    {
        // 构建时间标识符（不包含社区信息）
        $timeIdentifier = '';
        $availableCourses = [];
        if (is_array($timeSlot)) {
            $timeIdentifier = $timeSlot['year'] . '_' .
                $timeSlot['month'] . '_' .
                $timeSlot['day'] . '_' .
                $timeSlot['startTime'] . '-' .
                $timeSlot['endTime'];
        } else {
            $parts = explode(' ', $timeSlot);
            if (count($parts) >= 2) {
                $timeIdentifier = $parts[0] . '_' . $parts[1]; // 日期_时间段
            }
        }
        $courseId=$communityId;
        // 获取该社区可用的课程
        $availableCourses = array_map(function ($id) use ($communityId, $courseData) {
            return [
                'id' => $id,
                'name' => $courseData[$id],
                'community_id' => $communityId // 假设所有课程都适用于当前社区
            ];
        }, array_keys($courseData));

        // 过滤掉已在同一时间安排的课程，不管哪个社区
        $availableCourses = array_filter($availableCourses, function ($course) use ($timeIdentifier, $courseTimeSlotUsed, $communityId, $communityCoursesTaken) {
            $courseId=$communityId;
            $courseTimeKey = $courseId . '_' . $timeIdentifier;

            // 检查该课程是否已经被安排在该时间段
            $timeSlotAvailable = !isset($courseTimeSlotUsed[$courseTimeKey]);

            // 检查社区是否已经上过这门课程
            $courseNotTakenByCommunity = !in_array($courseId, $communityCoursesTaken[$communityId] ?? []);

            // 只有两个条件都满足才返回true
            return $timeSlotAvailable && $courseNotTakenByCommunity;
        });

        return $availableCourses;
    }

    public function table()
    {
        // 获取参数
        $month = Request::instance()->get('month', date('n'));
        $year = Request::instance()->get('year', date('Y'));
        $publicwelfare_id = Request::instance()->get('publicwelfare_id', 0);
        // 获取社区筛选参数，'0' 代表全部社区
        $community_code_filter = Request::instance()->get('community_code_filter', '0');
        $subject_id_filter = Request::instance()->get('subject_id_filter', '0'); // '0' for all subjects

        // 确保view对象已初始化
        if (!$this->view) {
            try {
                $this->view = new View();
            } catch (\Exception $e) {
                error_log('CommunityScheduler View re-initialization failed: ' . $e->getMessage());
                $this->view = null;
            }
        }

        // 获取公益项目列表
        $publicwelfareList = Db::name('fa_community_publicwelfare')
            ->where('status', 1)
            ->field('id, project_name')
            ->select();

        if ($this->view !== null) {
            $this->view->assign("publicwelfareList", $publicwelfareList);
        }

        // 生成页面缓存键
        $pageCacheKey = "schedule:table:page:{$publicwelfare_id}:{$year}:{$month}:{$community_code_filter}:{$subject_id_filter}";

        // 获取用于筛选下拉框的社区列表 (基于当前项目)
        $communityListForDropdown = ScheduleModel::getCommunityList($publicwelfare_id);
        $communityListForDropdown = is_array($communityListForDropdown) ? $communityListForDropdown : []; //确保是数组
        if ($this->view !== null) {
            $this->view->assign("communityListForDropdown", $communityListForDropdown);
        }

        // 获取用于筛选下拉框的学科列表 (基于当前项目)
        $subjectListForDropdown = ScheduleModel::getCourseNameList($publicwelfare_id);
        $subjectListForDropdown = is_array($subjectListForDropdown) ? $subjectListForDropdown : []; //确保是数组
        if ($this->view !== null) {
            $this->view->assign("subjectListForDropdown", $subjectListForDropdown);
        }

        // 生成缓存键
        $cacheKey = "schedule:table:{$publicwelfare_id}:{$year}:{$month}:{$community_code_filter}:{$subject_id_filter}";
        header("cachekey:" . $cacheKey);
        // 尝试从Redis获取缓存数据
        // 修改: 使用Redis原生get方法并反序列化
        $cachedViewData = $this->redis->get($cacheKey);
        if ($cachedViewData !== false) {
            header("iscache: true");
            $cachedViewData = unserialize($cachedViewData);
            // 将缓存数据分配到视图
            if ($this->view !== null) {
                foreach ($cachedViewData as $key => $value) {
                    $this->view->assign($key, $value);
                }
                $this->view->assign('community_code_filter', $community_code_filter);
                $this->view->assign('subject_id_filter', $subject_id_filter);
                $this->view->assign('publicwelfareList', $publicwelfareList);
            }
            // 添加isAjaxRequest变量
            $this->view->assign('isAjaxRequest', Request::instance()->isAjax());

            // 如果是Ajax请求，返回JSON数据
            if (Request::instance()->isAjax()) {
                $result = [
                    'code' => 1,
                    'msg' => '获取成功',
                    'data' => $cachedViewData
                ];
                $result['data']['community_code_filter'] = $community_code_filter;
                $result['data']['subject_id_filter'] = $subject_id_filter;
                return json($result);
            }
            echo $this->view->fetch("/course/schedule/table");
            exit;
        }

        // 将参数分配到视图
        $this->view->assign('year', $year);
        $this->view->assign('month', $month);
        $this->view->assign('publicwelfare_id', $publicwelfare_id);
        $this->view->assign('community_code_filter', $community_code_filter);
        $this->view->assign('subject_id_filter', $subject_id_filter);
        // 添加isAjaxRequest变量
        $this->view->assign('isAjaxRequest', Request::instance()->isAjax());

        // 1. 获取排课数据
        $scheduleQuery = Db::name('fa_course_schedule')->where('status', 1);

        // 根据年份筛选
        if ($year > 0) {
            $scheduleQuery->where('year', $year);
        }

        if ($publicwelfare_id > 0) {
            $scheduleQuery->where('publicwelfare_id', $publicwelfare_id);
        }

        // 新增：根据选择的社区编码筛选排课数据
        if ($community_code_filter !== '0') { // $community_code_filter is "1", "2", etc.
            // 假设数据库 fa_course_schedule.community_code 存储的是 "社区1", "社区2" 格式
            $targetCommunityDbKey = "社区" . $community_code_filter;
            $scheduleQuery->where('community_code', $targetCommunityDbKey);
            $targetCommunityDbName = $communityListForDropdown[$targetCommunityDbKey] ?? null;
        }

        // 新增：根据选择的学科中文名筛选排课数据
        if ($subject_id_filter !== '0' && !empty($subject_id_filter)) {
            // $subject_id_filter 现在是课程的中文名，例如 "养生操"

            // 1. 根据中文名从 fa_community_course_config 查找对应的 course code
            //    需要结合当前筛选的 publicwelfare_id 来确保唯一性，
            //    因为 getCourseList 也是基于这个 publicwelfare_id 生成的列表。
            $courseConfigQuery = \think\Db::name('fa_community_course_config')
                ->where('code', $subject_id_filter) // 匹配中文名
                ->where('status', 1)
                ->where('delete_time', null);

            if ($publicwelfare_id > 0) {
                $courseConfigQuery->where('publicwelfare_id', $publicwelfare_id);
            }

            $courseData = $courseConfigQuery->field('code')->find();

            if ($courseData && !empty($courseData['code'])) {
                $targetCourseCode = $courseData['code'];
                // 2. 使用获取到的 course_code 筛选 fa_course_schedule 表
                $scheduleQuery->where('course_code', $targetCourseCode);
            } else {
                // 如果中文名没有找到对应的 code (例如数据不一致或用户篡改),
                // 则不应该匹配到任何排课记录。
                $scheduleQuery->whereRaw('1=0');
            }
        }
        $scheduleQuery->order('year', 'asc');
        $scheduleQuery->order('month', 'asc');
        $scheduleQuery->order('day', 'asc');
        $scheduleQuery->order('timeslot', 'asc');
        $scheduleData = $scheduleQuery->select();
        $scheduleData = collection($scheduleData)->toArray();

        // 添加排序保持
        usort($scheduleData, function ($a, $b) {
            if ($a['year'] != $b['year']) return $a['year'] - $b['year'];
            if ($a['month'] != $b['month']) return $a['month'] - $b['month'];
            if ($a['day'] != $b['day']) return $a['day'] - $b['day'];

            // 更健壮的时间比较
            $getStartTime = function ($timeStr) {
                $parts = explode('-', $timeStr);
                return count($parts) > 0 ? strtotime($parts[0]) : 0;
            };
            return $getStartTime($a['timeslot']) - $getStartTime($b['timeslot']);
        });

        // 2. 获取时间段详细信息
        $detailedTimeSlots = $this->getTimeSlotDetails($publicwelfare_id);

        // 3. 整理时间段数据，按日期和时间段分组
        $organizedTimeSlots = [];
        foreach ($detailedTimeSlots as $slot) {
            $dayKey = $slot['day'];
            $timeKey = $slot['startTime'] . '-' . $slot['endTime'];

            if (!isset($organizedTimeSlots[$dayKey])) {
                $organizedTimeSlots[$dayKey] = [];
            }

            $organizedTimeSlots[$dayKey][$timeKey] = $slot;
        }

        // 添加调试信息，帮助诊断键值不匹配问题
        $debugInfo['organizedTimeSlotsKeys'] = [];
        foreach ($organizedTimeSlots as $day => $timeSlots) {
            $debugInfo['organizedTimeSlotsKeys'][$day] = array_keys($timeSlots);
        }

        // 4. 构建课程表格数据
        $tableData = [];
        $debugSchedule = [];
        $debug = [];

        // 获取社区映射信息
        $communityMapping = [];
        $communityIdMapping = [];

        // 从数据库加载社区映射关系
        $communityList = ScheduleModel::getCommunityList($publicwelfare_id);

        // 构建两种映射：社区编码到名称、ID到编码
        foreach ($communityList as $code => $name) {
            $communityMapping[$code] = $name;
        }

        // 获取所有社区的原始记录，用于创建详细的映射关系
        $communityRecords = Db::name('fa_community_code_config')
            ->where('status', 1)
            ->where('delete_time', null);

        if ($publicwelfare_id > 0) {
            $communityRecords->where('publicwelfare_id', $publicwelfare_id);
        }

        $communityRecords = $communityRecords->field('id, code, name')->select();

        // 构建更复杂的映射关系，包括数字ID和编码的映射
        $communityDetailMapping = [];
        foreach ($communityRecords as $record) {
            $communityDetailMapping[$record['id']] = [
                'code' => $record['code'],
                'name' => $record['name']
            ];

            // 也添加编码和名称的映射
            if (!empty($record['code'])) {
                $communityDetailMapping[$record['code']] = [
                    'id' => $record['id'],
                    'name' => $record['name']
                ];
            }

            // 添加名称的映射
            $communityDetailMapping[$record['name']] = [
                'id' => $record['id'],
                'code' => $record['code']
            ];
        }

        foreach ($scheduleData as $schedule) {
            $day = $schedule['day'];
            $courseCode = $schedule['course_code'];
            $communityCode = $schedule['community_code'];
            $month = $schedule['month'];
            $timeSlotCode = $schedule['time_slot_code'];
            $timeslot = isset($schedule['timeslot']) ? $schedule['timeslot'] : '';

            // 添加调试信息，记录每个排课记录的时间段代码
            if (!isset($debugInfo['scheduleTimeSlotCodes'])) {
                $debugInfo['scheduleTimeSlotCodes'] = [];
            }
            $debugInfo['scheduleTimeSlotCodes'][] = [
                'day' => $day,
                'timeSlotCode' => $timeSlotCode,
                'hasOrganizedTimeSlot' => isset($organizedTimeSlots[$day]) && isset($organizedTimeSlots[$day][$timeSlotCode])
            ];

            // 构建多种键值格式，增加匹配成功率
            $keyFormats = [];

            // 获取年份信息
            $scheduleYear = isset($schedule['year']) ? $schedule['year'] : $year;

            // 转换为数字字符串的键值格式（包含年份）
            $keyFormats[] = $scheduleYear . '_' . $month . '_' . intval($day) . '_' . $timeSlotCode . '_' . $communityCode;
            $keyFormats[] = intval($day) . '_' . $timeSlotCode . '_' . $communityCode . '_' . $month; // 兼容旧格式

            // 社区名称的键值格式（包含年份）
            if (isset($communityMapping[$communityCode])) {
                $keyFormats[] = $scheduleYear . '_' . $month . '_' . $day . '_' . $timeSlotCode . '_' . $communityMapping[$communityCode];

                // 安全地访问 organizedTimeSlots，避免 "Undefined array key" 错误
                if (isset($organizedTimeSlots[$day]) && isset($organizedTimeSlots[$day][$timeSlotCode]) && isset($organizedTimeSlots[$day][$timeSlotCode]["id"])) {
                    $keyFormats[] = $day . '_' . $organizedTimeSlots[$day][$timeSlotCode]["id"] . '_' . $communityCode . '_' . $schedule['time_zone_code']; // 兼容旧格式
                }
            }

            // 将所有键值格式添加到表格数据中
            foreach ($keyFormats as $key) {
                $tableData[$key] = $courseCode;
            }
        }

        // 5. 获取月份数据
        $timeZoneList = ScheduleModel::getTimeZoneList();
        $allMonths = [];
        $newAllMonths = [];

        foreach ($timeZoneList as $code => $name) {
            $formattedCode = sprintf('%02d', intval($code));
            $allMonths[$code] = $name; // 原始编码
            //$allMonths[$formattedCode] = $name; // 格式化编码

            // 如果名称不包含年月，使用默认格式
            if (!preg_match('/^\d+年\d+月$/', $name)) {
                $allMonths[$code] = $year . '年' . $code . '月';
                $allMonths[$formattedCode] = $year . '年' . $formattedCode . '月';
            }

            // 如果键名是"时区X"格式，提取数字部分作为新键
            if (preg_match('/^时区(\d+)$/', $code, $matches)) {
                $newKey = intval($matches[1]);
                $newAllMonths[$newKey] = $allMonths[$code];
            }
        }

        // 使用新的数字键数组替换原数组
        if (!empty($newAllMonths)) {
            $allMonths = $newAllMonths;
        }

        // 6. 准备视图数据
        $viewData = [
            'month' => $month,
            'year' => $year,
            'targetCommunityDbName' => $targetCommunityDbName ?? '',
            'publicwelfare_id' => $publicwelfare_id,
            'tableData' => $tableData,
            'organizedTimeSlots' => $organizedTimeSlots,
            'courseList' => ScheduleModel::getCourseList($publicwelfare_id),
            'communityList' => ScheduleModel::getCommunityList($publicwelfare_id),
            'timeZoneList' => ScheduleModel::getTimeZoneList($publicwelfare_id),
            'timeSlotList' => ScheduleModel::getTimeSlotList($publicwelfare_id),
            'communityMapping' => $communityMapping,
            'communityDetailMapping' => $communityDetailMapping,
            'debugInfo' => $debugInfo,
            'monthList' => [
                '1' => '1月',
                '2' => '2月',
                '3' => '3月',
                '4' => '4月',
                '5' => '5月',
                '6' => '6月',
                '7' => '7月',
                '8' => '8月',
                '9' => '9月',
                '10' => '10月',
                '11' => '11月',
                '12' => '12月'
            ],
            'allMonths' => $allMonths,
        ];

        // 根据社区筛选参数，确定实际要在表格中渲染的社区列表
        $communityToRender = [];
        // $communityList 在这里是 CourseSchedule::getCommunityList() 的结果，键是 "社区X"
        $sourceCommunityList = isset($viewData['communityList']) && is_array($viewData['communityList']) ? $viewData['communityList'] : [];

        if ($community_code_filter !== '0') { // $community_code_filter 是类似 "1", "2" 的字符串
            // 构建期望的键名，例如 "社区1"
            $targetKey = "社区" . $community_code_filter;
            if (isset($sourceCommunityList[$targetKey])) {
                $communityToRender = [$targetKey => $sourceCommunityList[$targetKey]];
            }
        } else {
            $communityToRender = $sourceCommunityList; // '0' means all communities from the project
        }

        $viewData['communityList'] = $communityToRender; // Use the filtered list for table rows

        // 8. 将数据传递给模板
        $this->view->assign($viewData);

        // 将视图数据缓存到Redis
        // 修改: 使用Redis原生setex方法并序列化数据
        $this->redis->setex($cacheKey, 3600, serialize($viewData)); // 缓存1小时

        // 如果是Ajax请求，返回JSON数据
        if (Request::instance()->isAjax()) {
            $result = [
                'code' => 1,
                'msg' => '获取成功',
                'data' => $cachedViewData
            ];
            $result['data']['community_code_filter'] = $community_code_filter;
            $result['data']['subject_id_filter'] = $subject_id_filter;
            return json($result);
        }

        // 渲染页面内容
        $pageContent = $this->view->fetch(); // 指定模板路径

        // 将页面内容缓存到Redis
        // 修改: 使用Redis原生setex方法并序列化数据
        $this->redis->setex($pageCacheKey, 3600, serialize(['html' => $pageContent])); // 缓存1小时

        echo $pageContent;
    }


    /**
     * 递归查找父级教学点的community_id
     */
    private function findCommunityIdRecursive($ocation_id, $depth = 0)
    {
        // 防止无限递归，最多查找5层
        if ($depth > 8 || empty($ocation_id)) {
            return null;
        }

        // 查询当前教学点的父级ID
        $parent_id = Db::name('fa_ocation')
            ->where('id', $ocation_id)
            ->value('pid');

        if (!$parent_id) {
            return null;
        }

        // 查询父级教学点是否有对应的社区ID
        $community_id = Db::name('eb_school_community')
            ->where('ocation_id', $parent_id)
            ->value('community_id');

        if ($community_id) {
            return $community_id;
        }

        // 如果父级也没有，继续向上查找
        return $this->findCommunityIdRecursive($parent_id, $depth + 1);
    }

    function insertAutoplantemp($publicwelfare_id, $scheduleData, $timeSlotInfo, $ocationId, $ocation_class_id, $courseInfo, $timeZoneCode, $parentTeachingOcationId, $topTeachingOcationId, $areaTeachingOcationId, $community_id, $courseId = null)
    {
        $courseCodeId = $this->model->getCourseCodeFromName($publicwelfare_id);
        // 构造Autoplantemp表的数据
        $autoplanData = [
            'table_type' => '2',
            'publicwelfare_id' => $publicwelfare_id, // 使用公益项目ID作为table_id
            'classes_id' => $ocation_class_id, // 课程ID作为classes_id
            'ocation_id' => $ocationId, // 社区ID作为教学点ID
            'ocation_class_id' => $ocation_class_id,
            'city_id' => $scheduleData['city_id'],
            'date' => $scheduleData['year'] . '-' . sprintf('%02d', $scheduleData['month']) . '-' . sprintf('%02d', $scheduleData['day']),
            'start_time' => $timeSlotInfo ? $timeSlotInfo['start_time'] : '09:00',
            'end_time' => $timeSlotInfo ? $timeSlotInfo['end_time'] : '10:00',
            'week' => date('w', strtotime($scheduleData['year'] . '-' . $scheduleData['month'] . '-' . $scheduleData['day'])), // 计算星期几
            'daytime' => $timeZoneCode, // 时段代码
            'teacher_id' => $courseInfo ? ($courseInfo['teacher_id'] ?? 0) : 0,
            'manager_id' => $courseInfo ? ($courseInfo['manager_id'] ?? 0) : 0,
            'status' => 1,
            'class_index' => 1, // 默认第1节课
            'oindex' => 1, // 默认第1节
            'oindex_count' => 1, // 默认1节课
            'count_total' => 1, // 默认总共1节课
            'bz' => '自动排课生成',
            // 新增字段
            'parent_teaching_ocation_id' => $parentTeachingOcationId, // 上级教学点ID
            'top_teaching_ocation_id' => $topTeachingOcationId, // 一级教学点ID
            'area_teaching_ocation_id' => $areaTeachingOcationId, // 一级教学点ID
            'school_id' => session('admin.school_id') ? session('admin.school_id') : 0, // 使用session函数安全获取学校ID
            'project_id' => $publicwelfare_id, // 项目ID
            'community_id' => $community_id, // 社区ID
            'is_free' => 1, // 是否免费
            'subject_lv' => $courseCodeId[$courseId] ?: ($courseCodeId[$courseInfo['id']] ?? 0), // 使用传入的课程ID，如果没有则使用courseInfo中的ID
            'addresslv_id' => $parentTeachingOcationId, // 地址级别ID
        ];
        $t_id = model("Autoplantemp")->insertUpdate(
            [$autoplanData],
            ['table_type', 'publicwelfare_id', 'ocation_id', 'date', 'start_time'],
            true
        );
    }


}
